package pl.edu.wsinf.lukaszwalczak.emailclient.view;

import java.util.List;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ComboBoxBuilder;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.ToolBar;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.TilePane;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.joda.time.DateTime;
import org.springframework.stereotype.Component;
import pl.edu.wsinf.lukaszwalczak.emailclient.controller.MainWindowController;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Attachment;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Folder;
import pl.edu.wsinf.lukaszwalczak.emailclient.pojo.Mail;

@Component
public class MailListView extends SplitPane {

    private MainWindowController mainWindowController;
    private Mail currentMail = null;
    private TableView<Mail> tableView;
    private Label subject;
    private Label sentDate;
    private Label from;
    private Label to;
    private ComboBox<Folder> folder;
    private WebView webView;
    private GridPane previewGrid;
    private TilePane attachmentsContainer;

    public MailListView() {

        // Lista
        final ObservableList<Mail> data = FXCollections.<Mail>emptyObservableList();

        TableColumn iconColumn = new TableColumn();
        iconColumn.setMinWidth(30);
        iconColumn.setMaxWidth(30);
        iconColumn.setCellValueFactory(new PropertyValueFactory("read"));
        iconColumn.setCellFactory(new Callback<TableColumn<Mail, Boolean>, TableCell<Mail, Boolean>>() {
            @Override
            public TableCell<Mail, Boolean> call(TableColumn<Mail, Boolean> param) {
                TableCell<Mail, Boolean> cell = new TableCell<Mail, Boolean>() {
                    @Override
                    public void updateItem(Boolean item, boolean empty) {
                        ImageView imageView = new ImageView();
                        imageView.setFitHeight(16);
                        imageView.setFitWidth(16);
                        Image image = null;
                        if (item != null) {
                            if (item) {
                                image = new Image(MailListView.class.getResourceAsStream("/icons/mail_read.png"));
                            } else {
                                image = new Image(MailListView.class.getResourceAsStream("/icons/mail_unread.png"));
                            }
                        }
                        imageView.setImage(image);
                        setGraphic(imageView);
                    }
                };
                cell.setAlignment(Pos.CENTER);
                return cell;
            }
        });

        TableColumn senderColumn = new TableColumn();
        senderColumn.setText("Nadawca");
        senderColumn.setCellValueFactory(new PropertyValueFactory("from"));

        TableColumn subjectColumn = new TableColumn();
        subjectColumn.setText("Temat");
        subjectColumn.setMinWidth(200);
        subjectColumn.setCellValueFactory(new PropertyValueFactory("subject"));

        TableColumn dateColumn = new TableColumn();
        dateColumn.setText("Data nadania");
        dateColumn.setCellValueFactory(new Callback<CellDataFeatures<Mail, String>, ObservableValue<String>>() {
            @Override
            public ObservableValue<String> call(CellDataFeatures<Mail, String> cellData) {
                DateTime date = cellData.getValue().getSentDate();
                String result = "";
                if (date != null) {
                    result = date.toString("dd/MM/yyyy HH:mm");
                }
                return new ReadOnlyObjectWrapper(result);
            }
        });

        tableView = new TableView<>();
        tableView.setItems(data);
        tableView.getColumns().addAll(iconColumn, senderColumn, subjectColumn, dateColumn);
        tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        this.getItems().add(tableView);

        // Listener na zaznaczenie wiersza
        tableView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Mail>() {
            @Override
            public void changed(ObservableValue<? extends Mail> observable,
                    Mail oldValue, Mail selected) {
                if (observable != null && observable.getValue() != null) {
                    updateMailPreview(selected);
                }
            }
        });

        // Podglad maila
        VBox preview = new VBox(0);

        // Toolbar
        ToolBar toolbar = new ToolBar();
        Button newEmailCreateButton = ViewHelper.createButton("Napisz", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                mainWindowController.showMailCreateWindow(currentMail);
            }
        }, "mail-new-16.png", null, 28d);
        toolbar.getItems().add(newEmailCreateButton);

        Button newEmailAnswerButton = ViewHelper.createButton("Odpowiedz", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (currentMail != null) {
                    mainWindowController.showMailReplyWindow(currentMail);
                }
            }
        }, "mail-rpl-16.png", null, 28d);
        toolbar.getItems().add(newEmailAnswerButton);

        Button replyAllButton = ViewHelper.createButton("Odpowiedz wszystkim", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (currentMail != null) {
                    mainWindowController.showMailReplyAllWindow(currentMail);
                }
            }
        }, "mail-reply-all-16.png", null, 28d);
        toolbar.getItems().add(replyAllButton);

        Button newEmailEditButton = ViewHelper.createButton("Przekaż", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (currentMail != null) {
                    mainWindowController.showMailForwardWindow(currentMail);
                }
            }
        }, "mail-fwd-16.png", null, 28d);
        toolbar.getItems().add(newEmailEditButton);

        Button newEmailDeleteButton = ViewHelper.createButton("Usuń", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (currentMail != null) {
                    mainWindowController.moveToTrash(currentMail);
                }
            }
        }, "trash-16.gif", null, 28d);
        toolbar.getItems().add(newEmailDeleteButton);

        StringConverter converter = new StringConverter<Folder>() {
            @Override
            public String toString(Folder t) {
                return t.getName();
            }

            @Override
            public Folder fromString(String string) {
                return folder.getValue();
            }
        };
        folder = ComboBoxBuilder.<Folder>create().
                promptText("Przenieś do").
                converter(converter).
                build();
        toolbar.getItems().add(folder);
        folder.setPrefWidth(120);
        folder.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Folder>() {
            @Override
            public void changed(ObservableValue<? extends Folder> ov, Folder t, Folder newValue) {
                if (newValue != null) {
                    mainWindowController.moveToFolder(currentMail, newValue.getName());
                }
            }
        });

        // Nagłówki maila
        previewGrid = new GridPane();
        previewGrid.setHgap(10);
        previewGrid.setVgap(10);
        previewGrid.setPadding(new Insets(10, 20, 10, 20));
        previewGrid.setId("mail-preview-grid");

        previewGrid.add(new Label("Temat: "), 0, 0);
        subject = new Label();
        previewGrid.add(subject, 1, 0);

        previewGrid.add(new Label("Data wysłania: "), 0, 1);
        sentDate = new Label();
        previewGrid.add(sentDate, 1, 1);

        previewGrid.add(new Label("Od: "), 0, 2);
        from = new Label();
        previewGrid.add(from, 1, 2);

        previewGrid.add(new Label("Do: "), 0, 3);
        to = new Label();
        previewGrid.add(to, 1, 3);

        previewGrid.add(new Label("Załączniki: "), 0, 4);
        attachmentsContainer = new TilePane();
        previewGrid.add(attachmentsContainer, 1, 4);

        // Tresc wiadomosci
        webView = new WebView();
        preview.getChildren().addAll(toolbar, previewGrid, webView);

        this.getItems().add(preview);

        this.setDividerPositions(0.3, 0.7);
        this.setOrientation(Orientation.VERTICAL);
    }

    private void updateMailPreview(Mail mail) {
        currentMail = mail;
        String content = null;
        String subjectText = "";
        String sentDateText = "";
        String fromText = "";
        String toText = "";
        folder.setValue(null);
        attachmentsContainer.getChildren().clear();
        if (mail != null) {
            if (mail.getContent() != null) {
                content = mail.getContent().getHtml() != null
                        ? mail.getContent().getHtml()
                        : mail.getContent().getPlain();
            }
            if (mail.getSubject() != null) {
                subjectText = mail.getSubject();
            }
            if (mail.getSentDate() != null) {
                sentDateText = mail.getSentDate().toString("dd/MM/yyyy HH:mm");
            }
            if (mail.getFrom() != null) {
                fromText = mail.getFrom().toString();
            }
            if (mail.getTo() != null) {
                toText = mail.getTo().toString().substring(1, mail.getTo().toString().length() - 1);
            }

            List<Folder> folders = mainWindowController.getFolders(mail.getAccount());
            folder.setItems(FXCollections.observableArrayList(folders));

            if (mail.getAttachments() != null && !mail.getAttachments().isEmpty()) {
                for (final Attachment attachment : mail.getAttachments()) {
                    final Hyperlink link = new Hyperlink(attachment.getFileName());
                    link.getStyleClass().add("attachment-link");
                    final ContextMenu contextMenu = new ContextMenu();
                    MenuItem openItem = new MenuItem("Otwórz");
                    openItem.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent t) {
                            mainWindowController.handleAttachmentOpen(attachment, false);
                        }
                    });
                    MenuItem saveItem = new MenuItem("Zapisz");
                    saveItem.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent t) {
                            mainWindowController.handleAttachmentOpen(attachment, true);
                        }
                    });
                    contextMenu.getItems().addAll(openItem, saveItem);
                    link.setContextMenu(contextMenu);
                    link.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent t) {
                            contextMenu.show(link, Side.BOTTOM, 0, 0);
                        }
                    });
                    attachmentsContainer.getChildren().add(link);
                }
            } else {
                attachmentsContainer.getChildren().add(new Label("-"));
            }
        }
        subject.setText(subjectText);
        sentDate.setText(sentDateText);
        from.setText(fromText);
        to.setText(toText);
        webView.getEngine().loadContent(content != null ? content : "");
    }

    public void setTableViewItems(List<Mail> mails) {
        if (mails != null) {
            tableView.setItems(FXCollections.<Mail>observableList(mails));
            if (!mails.isEmpty()) {
                updateMailPreview(mails.get(0));
            } else {
                updateMailPreview(null);
            }
            markRead();
        }
    }

    public Mail getSelected() {
        return tableView.getSelectionModel().getSelectedItem();
    }

    public void addSelectionListener(ChangeListener<Mail> listener) {
        tableView.getSelectionModel().selectedItemProperty().addListener(listener);
    }

    public void markRead() {
        int i = 0;
        for (Node n : tableView.lookupAll("TableRow")) {
            if (n instanceof TableRow && !tableView.getItems().isEmpty()) {
                TableRow row = (TableRow) n;
                Mail item = tableView.getItems().get(i);
                if (!item.isRead()) {
                    row.getStyleClass().add("mail-unread-mark");
                } else {
                    row.getStyleClass().remove("mail-unread-mark");
                }
                i++;
                if (i == tableView.getItems().size()) {
                    break;
                }
            }
        }
    }

    public void setMainWindowController(MainWindowController mainWindowController) {
        this.mainWindowController = mainWindowController;
    }
}
